<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
<link rel="stylesheet" href="../style/journal.css" type="text/css" />
<style type="text/css"><!--
.googleadsense {
	margin: 2px;
	padding: 0px;
//--></style><script src="http://www.google-analytics.com/urchin.js" type="text/javascript">
</script>
<script type="text/javascript">
_uacct = "UA-65008-1";
urchinTracker();
</script><title>Tips from Perl Best Practices</title>
</head>
<body>
<a href="index.html">Journal</a>(2005) | <a href="../blog/"><b>Blog</b></a>(2006) | <a href="http://www.fayland.org/cgi-bin/random_link.pl">RandomLink</a> | <a href="AboutFayland.html">WhoAmI</a> | <a href="LiveBookmark.html">LiveBookmark</a> | <a href="http://www.fayland.org/">HomePage</a>
<p><&lt;Previous: <a href="PBP1.html">一种代码风格</a>&nbsp;&nbsp;>>Next: <a href="Utils.html">Scalar::Util, List::Util, List::MoreUtils</a></p>
<h1>Tips from Perl Best Practices</h1>
<div class='content'>
<p>Category: <a href='BookNotes.html'>BookNotes</a> &nbsp; Keywords: <b>tips</b></p><ul>
<li>use Readonly instead of use constant.<br />
用 use Readonly 来代替 use constant</li>
</ul>

<p>原因有二：一是 use constant 不能内插。例如：</p>


<pre># 用 Readonly 的两个例子
use Readonly;
Readonly my $DEAR      =&gt; 'Greetings to you,';
Readonly my $SINCERELY =&gt; 'May Heaven guard you from all misfortune,';

$msg = &lt;&lt;&quot;END_MSG&quot;;
$DEAR $target_name

$scam_pitch

$SINCERELY

$fake_name
END_MSG

Readonly my $LINES_PER_PAGE =&gt; 42;
$margin{$LINES_PER_PAGE}                 # sets $margin{'42'}
    = $MAX_LINES - $LINES_PER_PAGE;</pre>




<pre># 对应麻烦的用 constant
use constant (
    DEAR      =&gt; 'Greetings to you,',
    SINCERELY =&gt; 'May Heaven guard you from all misfortune,',
);

$msg = DEAR . $target_name
       . &quot;$scam_pitch\n\n&quot;
       . SINCERELY
       . &quot;\n\n$fake_name&quot;;

use constant (
    LINES_PER_PAGE =&gt; 42
);

$margin{LINES_PER_PAGE}               # sets $margin{'LINES_PER_PAGE'}
    = MAX_LINES - LINES_PER_PAGE;</pre>


<p>第二个原因是作用域范围。Readonly 能定义不同的作用域，而 constant 只有包作用域。</p>

<ul>
<li>If you're forced to modify a package variable, localize it.<br />
如果需要改变一个包变量，请直接 local.</li>
</ul>



<pre>use YAML;

# Do
local $YAML::Indent = 4;

# NOT
$YAML::Indent = 4;</pre>


<p>注意要初始化此变量。当 local 此变量时，它的值默认为 undef.</p>


<pre>local $YAML::Indent; # 这里的值为 undef
local $YAML::Indent = $YAML::Indent; # 这样才可能是你想要的</pre>



<ul>
<li>Avoid subscripting arrays or hashes within loops.<br />
避免在循环中使用下标数组或散列。</li>
</ul>


<pre># Do
for my $client (@clients) {
    $client-&gt;tally_hours(  );
    $client-&gt;bill_hours(  );
    $client-&gt;reset_hours(  );
}

# Do NOT
for my $n (0..$#clients) {
    $clients[$n]-&gt;tally_hours(  );
    $clients[$n]-&gt;bill_hours(  );
    $clients[$n]-&gt;reset_hours(  );
}</pre>



<ul>
<li>Use grep instead of for when searching for values in a list.<br />
当在列表中搜寻值时，首先考虑 grep 而不是 for.<br />
Use for instead of map when transforming a list in place.<br />
当在列表中改变其中的值时，首先考虑 for 而不是 map.</li>
</ul>

<ul>
<li>Use scalar reverse to reverse a scalar.<br />
使用 scalar reverse 来反转一个标量。<br />
在某些情况下，前面不加 scalar 也是可以成功的，但是很容易造成错误。如：</li>
</ul>


<pre># 下两句是一样效果的
my $visible_email_address = reverse $actual_email_address;
my $visible_email_address = scalar reverse $actual_email_address;

# 但这两句效果不一样，子程序默认接受数组。所以可能就没有达到你要的目的。
add_email_addr(reverse $email_address); # 列表环境
add_email_addr(scalar reverse $email_address); # 标量环境</pre>



<ul>
<li>对于在 sort 中重复运行多次的函数，考虑使用用散列缓存函数运行结果或使用 Memoize</li>
</ul>


<pre># 对于如下代码
Use Digest::SHA qw( sha512 );

# Sort by SHA-512 digest of scripts
@sorted_scripts
    = sort { sha512($a) cmp sha512($b) } @scripts;

# 请用下面两则代替
my %sha512_of;

# Sort by SHA-512 digest of scripts
@sorted_scripts
    = sort { ($sha512_of{$a} ||= sha512($a))
                     cmp
             ($sha512_of{$b} ||= sha512($b))
           }
           @scripts;

# 或者更简洁
# Make the SHA-512 digest function self-caching...
use Memoize;
memoize('sha512');

# Sort by auto-cached SHA-512 digest of scripts...
@sorted_scripts = sort { sha512($a) cmp sha512($b) } @scripts;</pre>


<p>Damain 还推荐了 Sort::Maker 来执行相关 sort 任务。</p>

<h3>Finally</h3>
说实话我对英文也不是很感冒，所以读起来也是跳着读的。没怎么仔细看。所以也就这样了。</div>
<p><&lt;Previous: <a href="PBP1.html">一种代码风格</a>&nbsp;&nbsp;>>Next: <a href="Utils.html">Scalar::Util, List::Util, List::MoreUtils</a></p>
<p><strong>Options:</strong> <a href='http://del.icio.us/post?title=Tips%20from%20Perl%20Best%20Practices&url=http://www.fayland.org/journal/PBP2.html'>+Del.icio.us</a></p>
<strong>Related items</strong>
<ul><li><a href='PBP3.html'>Tips from Perl Best Practices, Part 2</a> < <span class='digit'>2005-09-22 00:29:34</span> ></li></ul>
Created on <span class="digit">2005-09-13 16:57:52</span>, Last modified on <span class="digit">2005-09-13 21:10:45</span><br />
Copyright 2004-2005 All Rights Reserved. Powered by <a href="Eplanet.html">Eplanet</a> && <a href='http://catalyst.perl.org'>Catalyst</a> 5.62.
</body>
</html>